import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class DataConnection{
	public final static int DATA_BLOCK_SIZE = 2048;

	private Socket socket;
	private Reciever dr;
	private Sender ds;

	public DataConnection(String serverAddress, int port, Reciever dr) throws UnknownHostException, IOException {
		setValues(serverAddress, port);
		this.dr = dr;
	}

	public DataConnection(String serverAddress, int port, Sender ds) throws UnknownHostException, IOException {
		setValues(serverAddress, port);
		this.ds = ds;
	}
	
	private void setValues(String serverAddress, int port) throws UnknownHostException, IOException {
		socket = new Socket(serverAddress,port);
		socket.setSoTimeout(30*1000);
	}
	public void startWriting() throws IOException {
			OutputStream os = socket.getOutputStream();
			int byteCount;
			byte[] bytes = new byte[DATA_BLOCK_SIZE];
			while((byteCount = ds.sendBytes(bytes)) > 0) {
				os.write(bytes,0,byteCount);
			}
			socket.close();
			ds.closed();

	}

	public void startReading() throws IOException {
			InputStream is = socket.getInputStream();
			int byteCount;
			byte[] bytes = new byte[DATA_BLOCK_SIZE];
			while((byteCount = is.read(bytes)) > 0) {
				dr.bytesRecieved(bytes, byteCount);
				bytes = new byte[DATA_BLOCK_SIZE];
			}
			socket.close();
			dr.closed();
	}
	
	public static abstract class Reciever{
		StringBuffer sb;
		public Reciever() {
			sb = new StringBuffer();
		}
		void bytesRecieved(byte[] bytes,int byteCount) {
			for(int i = 0;i<byteCount;i++){
				if(( bytes[i] == '\n' ||
					 bytes[i] == '\r') 
					 && sb.length() != 0) {
					lineRecieved(sb.toString());
					sb = new StringBuffer();
					if(i+1 < byteCount) {
						if(bytes[i+1] == '\n' ||bytes[i+1] ==  '\r') {
							i++;
						}
					}
				}
				else {
					sb.append((char)bytes[i]);
				}
			}
		}
		void lineRecieved(String s){
		}
		void closed(){}
	}

	public static abstract class Sender {
		int sendBytes(byte[] bytes) {return 0;}
		public void closed(){}
	}
}

